﻿using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System;
using System.Security.Cryptography;
using System.Text;

namespace TK.Common.Tools
{
    /// <summary>
    /// Hash密码算法
    /// </summary>
    public static class PasswordHasher
    {
        /// <summary>
        /// 获取Hash密码
        /// </summary>
        public static string HashPassword(string password)
        {
            var salt = GenerateSalt();
            var hash = HashPassword(password, salt);
            return $"{salt}.{hash}";
        }

        /// <summary>
        /// 校验Hash密码
        /// </summary>
        public static bool VerifyHashedPassword(string password, string storePassword)
        {
            if (string.IsNullOrEmpty(password))
            {
                return false;
            }

            if (string.IsNullOrEmpty(storePassword))
            {
                return false;
            }

            var parts = storePassword.Split('.');
            if (parts.Length != 2)
            {
                return false;
            }

            var salt = parts[0];
            var hash = parts[1];

            return HashPassword(password, salt) == hash;
        }

        /// <summary>
        /// 获取25-30开头的长度为16-24位的数字
        /// </summary>
        public static string GetRandomNumber()
        {
            var rand = new Random(Guid.NewGuid().GetHashCode());

            var header = rand.Next(25, 31);
            var length = rand.Next(14, 23);
            var randCode = new StringBuilder();
            for (var i = 0; i < length; i++)
            {
                randCode.Append(rand.Next(0, 10));
            }

            return $"{header}{randCode}";
        }

        #region private methods

        private static string HashPassword(string password, string salt)
        {
            var valueBytes = KeyDerivation.Pbkdf2(
                password: password,
                salt: Encoding.UTF8.GetBytes(salt),
                prf: KeyDerivationPrf.HMACSHA512,
                iterationCount: 10000,
                numBytesRequested: 256 / 8);

            return Convert.ToBase64String(valueBytes);
        }

        private static string GenerateSalt()
        {
            var bytes = new byte[128 / 8];
            using (var generator = RandomNumberGenerator.Create())
            {
                generator.GetBytes(bytes);
                return Convert.ToBase64String(bytes);
            }
        }

        #endregion
    }
}
